import datetime
import os

from flask import Blueprint, request, jsonify, current_app
from werkzeug.exceptions import RequestEntityTooLarge
from werkzeug.utils import secure_filename
from flask import send_from_directory, abort
from app.Services.TodoServices.TodoLogServices import TodoLogService
from app.Services.TodoServices.TodoServices import TodoService  # 导入Service层
from app.Utils.Decorator.ToDoDecorator import update_main_task_focus_time
from app.Utils.Decorator.UserIdDecorator import inject_user_id
from app.Utils.Utils import CommonUtils, return_response_

# 创建Blueprint，定义接口前缀
todo_bp = Blueprint("todo",
                    import_name=__name__,
                    url_prefix="/api/todo")


# ================= 工具函数 =================
def allowed_file(filename):
    """校验文件后缀是否允许（保留原始后缀）"""
    # 分割文件名和后缀，不改变原始后缀（如：paste-123456.png → 保留.png）
    return True


# ================= 路由 =================
@todo_bp.route('/upload', methods=['POST'])
def upload_file():
    file = request.files['file']

    # 2. 校验文件类型（保留原始后缀）
    if file and allowed_file(file.filename):
        # 安全处理文件名（避免特殊字符，保留原始后缀）
        original_filename = secure_filename(file.filename)
        # 分割原始文件名和后缀（如：test.jpg → ('test', 'jpg')）
        name_without_ext, ext = os.path.splitext(original_filename)
        # 添加时间戳避免文件名重复（格式：原始文件名_时间戳.原始后缀）
        timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        safe_filename = f"{name_without_ext}_{timestamp}{ext}"  # 保留原始后缀

        # 3. 保存文件到上传目录
        file_save_path = os.path.join(current_app.config['UPLOAD_FOLDER'], safe_filename)
        file.save(file_save_path)
        print(f"文件保存路径：{file_save_path}")

        # 4. 构建可访问的文件URL（关键：前端能直接通过URL打开）
        # 格式：http://服务器IP:端口/api/uploads/文件名
        # 注意：替换为你的服务器实际IP（本地开发用localhost，部署后用服务器公网IP）
        server_ip = 'localhost'  # 本地开发用localhost；部署后改为服务器公网IP（如：192.168.1.100）
        server_port = 5033  # 与你Flask服务的端口一致（前端action配置的是5033）
        file_url = f"http://{server_ip}:{server_port}/api/todo/uploads/{safe_filename}"
        print(f"文件访问URL：{file_url}")

        # 5. 返回结果（含可访问的URL，前端可用于替换Blob URL）

        data = {
            'file_url': file_url,  # 可直接访问的图片URL
            'filename': safe_filename,  # 保存后的文件名
            'original_filename': original_filename  # 原始文件名（可选）
        }
        return return_response_(True, data)


@todo_bp.route('/uploads/<filename>', methods=['GET'])
@inject_user_id(default_user_id=1)  # 启用装饰器，默认值设为 1
def get_uploaded_image(filename):
    """
    通过 GET 请求返回上传的图片
    访问路径：http://localhost:5033/api/uploads/xxx.png（与前端 file_url 对应）
    """
    # 1. 安全校验文件名（避免路径穿越攻击，如 ../../etc/passwd）
    safe_filename = secure_filename(filename)

    # 4读取文件并返回给前端（自动处理 Content-Type）
    # send_from_directory：安全地从指定目录返回文件，避免路径遍历
    return send_from_directory(
        directory=current_app.config['UPLOAD_FOLDER'],
        path=safe_filename,
        as_attachment=False  # False：直接在浏览器预览；True：触发下载
    )


@todo_bp.route("/list", methods=["POST"])
@inject_user_id(default_user_id=1)  # 启用装饰器，默认值设为 1
def get_todo_list(user_id):
    """
    分页查询Todo列表（支持多条件筛选）
    ---
    请求方式：GET
    请求参数（Query参数）：
        user_id (int, 可选): 用户ID，筛选指定用户的Todo
        is_done (int, 可选): 完成状态（0=未完成，1=已完成）
        importance (int, 可选): 重要性（0=重要且紧急，1=重要不紧急，2=紧急不重要，3=不紧急不重要）
        page (int, 可选): 页码，默认1
        per_page (int, 可选): 每页条数，默认10
    响应格式：
        成功 (200):
            {
                "code": 200,
                "message": "查询成功",
                "data": {
                    "items": [Todo详情字典列表，含外键name],
                    "total": 总条数,
                    "page": 当前页码,
                    "per_page": 每页条数,
                    "pages": 总页数
                }
            }
        失败 (500):
            {
                "code": 500,
                "message": "查询失败原因"
            }
    """

    # 接收Query参数（支持类型转换和默认值）
    params = {
        "deadline": request.json.get("deadline", None),
        "is_done": request.json.get("is_done", None),
    }
    # 直接使用装饰器注入的 user_id
    params["user_id"] = user_id
    # 调用Service层查询
    success, result = TodoService.get_all_todos(**params)
    return return_response_(success, result)


@todo_bp.route("/<int:todo_id>", methods=["GET"])
def get_todo_detail(todo_id):
    """
    根据ID查询单个Todo详情（含外键关联名称）
    ---
    请求方式：GET
    请求参数（路径参数）：
        todo_id (int, 必选): Todo主键ID
    响应格式：
        成功 (200):
            {
                "code": 200,
                "message": "查询成功",
                "data": {Todo详情字典，含user_name/goal_name/project_name}
            }
        失败 (404/500):
            {
                "code": 404/500,
                "message": "查询失败原因"
            }
    """
    # 调用Service层查询单个详情
    status, result = TodoService.get_todo_by_id(todo_id)

    if status:
        return return_response_(status, result)
    else:
        return return_response_(status, result)


@todo_bp.route("/add", methods=["POST"])
@inject_user_id(default_user_id=1)  # 启用装饰器，默认值设为 1
def create_todo(user_id):
    """
    新增Todo任务
    ---
    请求方式：POST
    请求体（JSON）：
        {
            "user_id": int, 必选: 用户ID（关联user_info表）
            "description": str, 必选: 任务描述
            "deadline": str, 必选: 截止日期（格式：YYYY-MM-DD）
            "goal_id": int, 必选: 目标ID（关联goal_cate表）
            "self_score": int, 必选: 自我评分（0-5）
            "importance": int, 必选: 重要性（0-3）
            "remark": str, 必选: 备注/日志
            "project_id": int, 可选: 项目ID（关联program表，可传null取消关联）
            "is_done": int, 可选: 完成状态（0=未完成，1=已完成，默认0）
            "focus_time": int, 可选: 专注时长（分钟，默认0）
            "attachment": str, 可选: 附件路径
        }
    响应格式：
        成功 (201):
            {
                "code": 201,
                "message": "新增成功（含Todo ID）"
            }
        失败 (400/500):
            {
                "code": 400/500,
                "message": "新增失败原因"
            }
    """

    # 接收JSON请求体
    description = request.json.get("description", None)
    # 截止日期
    deadline_ = request.json.get("deadline", None)
    print(deadline_)

    # 调用Service层新增
    success, msg = TodoService.add_todo(user_id=user_id, description=description,deadline=deadline_)

    return return_response_(success, msg)


@todo_bp.route("/update_todo", methods=["POST"])
@inject_user_id(default_user_id=1)  # 启用装饰器，默认值设为 1
def update_todo(user_id):
    """
    根据ID修改Todo任务（支持部分字段更新）
    ---
    请求方式：PUT
    请求参数（路径参数）：
        todo_id (int, 必选): 要修改的Todo主键ID
    请求体（JSON）：
        {
            "description": str, 可选: 任务描述
            "deadline": str, 可选: 截止日期（格式：YYYY-MM-DD）
            "goal_id": int, 可选: 目标ID（关联goal_cate表）
            "project_id": int, 可选: 项目ID（关联program表，可传null取消关联）
            "self_score": int, 可选: 自我评分（0-5）
            "importance": int, 可选: 重要性（0-3）
            "is_done": int, 可选: 完成状态（0=未完成，1=已完成）
            "remark": str, 可选: 备注/日志
            "focus_time": int, 可选: 专注时长（分钟）
            "attachment": str, 可选: 附件路径
        }
    响应格式：
        成功 (200):
            {
                "code": 200,
                "message": "修改成功"
            }
        失败 (400/404/500):
            {
                "code": 400/404/500,
                "message": "修改失败原因"
            }
    """

    # 接收JSON请求体
    todo_id = request.json.get("id", None)
    update_data = request.json
    update_data.pop("log_info", None)
    update_data.pop("goal_name", None)
    update_data.pop("id", None)
    update_data.pop("program_name", None)
    update_data.pop("submit_time", None)
    update_data.pop("user_id", user_id)
    update_data.pop("username", None)
    update_data.pop("goal_status", None)
    # 调用Service层修改
    success, msg = TodoService.update_todo(todo_id, **update_data)

    return return_response_(success, msg)


@todo_bp.route('/get_by_id', methods=["POST"])
def get_todo_by_id():
    """
    根据任务id获取任务数据
    """
    todo_id = request.json.get("id", None)
    success, msg = TodoService.get_todo_by_id(todo_id)
    return return_response_(success, msg)


@todo_bp.route("/del_todo", methods=["POST"])
def delete_todo():
    """
    根据ID删除Todo任务
    ---
    请求方式：DELETE
    请求参数（路径参数）：
        todo_id (int, 必选): 要删除的Todo主键ID
    响应格式：
        成功 (200):
            {
                "code": 200,
                "message": "删除成功"
            }
        失败 (404/500):
            {
                "code": 404/500,
                "message": "删除失败原因"
            }
    """
    todo_id = int(request.json.get("todo_id"))
    # 调用Service层删除
    success, msg = TodoService.delete_todo(todo_id)
    return return_response_(success, msg)


# todo日志相关
@todo_bp.route("/log/add", methods=["POST"])
@inject_user_id(default_user_id=1)  # 启用装饰器，默认值设为 1
def add_log(user_id):
    """
    新增Todo日志，todo主ID必填。
    """
    todo_log_dict = {'user_id': int(user_id),
                     'task_id': int(request.json.get("task_id")),
                     'log_title': request.json.get("log_title"),
                     'description': request.json.get("description"),
                     'self_score': int(request.json.get("self_score")),
                     'focus_time': request.json.get("focus_time"),
                     'submit_time': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                     'attachment': request.json.get("attachment")
                     }

    status, msg = TodoLogService.create_todo_log(todo_log_dict)
    return return_response_(status, msg)


@todo_bp.route("/log/get_log_by_task_id", methods=["POST"])
@inject_user_id(default_user_id=1)  # 启用装饰器，默认值设为 1
def get_log_by_task_id(user_id):
    """
    根据主任务id获取对应的日志信息。
    """
    task_id = int(request.json.get("task_id"))
    status, res = TodoLogService.get_todo_logs_by_condition(**{
        'user_id': user_id,
        'task_id': task_id
    })
    return return_response_(status, res)


@todo_bp.route("/log/delete_log_by_log_id", methods=["POST"])
@inject_user_id(default_user_id=1)  # 启用装饰器，默认值设为 1
def delete_log_by_log_id(user_id):
    """
    根据日志id删除日志记录。
    """
    log_id = int(request.json.get("log_id"))
    status, res = TodoLogService.delete_todo_log(log_id, user_id)
    return return_response_(status, res)


@todo_bp.route("/log/update_log_by_log_id", methods=["POST"])
@inject_user_id(default_user_id=1)  # 启用装饰器，默认值设为 1
def update_log_by_log_id(user_id):
    """
    根据日志id更新日志记录。
    """
    log_data = request.json
    log_data.pop('submit_time')
    log_data.pop('task_id')
    log_data.pop('user_id')
    log_id = log_data.pop('id')
    status, res = TodoLogService.update_todo_log(log_id=log_id, update_dict=log_data, operator_user_id=user_id)
    return return_response_(status, res)

# 根据项目id获取对应的todo信息
@todo_bp.route("/get_todo_by_project_id", methods=["POST"])
def get_todo_by_project_id():
    """
    根据项目id获取对应的todo信息。
    """
    project_id = int(request.json.get("project_id"))
    status, res = TodoService.get_todo_by_project_id(project_id)
    return return_response_(status, res,message=res)
